package com.atguigu.ssyx.search.service.impl;

import com.atguigu.ssyx.activity.client.ActivityFeignClient;
import com.atguigu.ssyx.client.product.ProductFeignClient;
import com.atguigu.ssyx.common.auth.AuthContextHolder;
import com.atguigu.ssyx.enums.SkuType;
import com.atguigu.ssyx.model.product.Category;
import com.atguigu.ssyx.model.product.SkuInfo;
import com.atguigu.ssyx.model.search.SkuEs;
import com.atguigu.ssyx.search.repository.SkuRepository;
import com.atguigu.ssyx.search.service.SkuService;
import com.atguigu.ssyx.vo.search.SkuEsQueryVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * Created with IntelliJ IDEA.
 * ClassName: SkuServiceImpl
 * Package: com.atguigu.ssyx.search.service.impl
 * Description:
 * User: fzykd
 *
 * @Author: LQH
 * Date: 2023-09-27
 * Time: 11:21
 */

@Service
public class SkuServiceImpl implements SkuService {

    @Autowired
    private SkuRepository skuRepository;
    //操作ES的接口

    @Autowired
    private ProductFeignClient productFeignClient;
    //定义的远程调用的接口

    @Autowired
    private ActivityFeignClient activityFeignClient;

    @Autowired
    private RedisTemplate redisTemplate;

    //上架
    @Override
    public void upperSku(Long skuId) {
        //远程调用

        //1.通过远程调用 根据skuId获取相关信息
        SkuInfo skuInfo = productFeignClient.getSkuInfo(skuId);
        if (skuInfo == null) {
            return;
        }
        Category category = productFeignClient.getCategory(skuInfo.getCategoryId());

        //2.获取数据封装SkuEs对象
        SkuEs skuEs = new SkuEs();
        if (category != null) {
            skuEs.setCategoryId(category.getId());
            skuEs.setCategoryName(category.getName());
        }
        //封装Sku信息
        skuEs.setId(skuInfo.getId());
        skuEs.setKeyword(skuInfo.getSkuName() + "," + skuEs.getCategoryName());
        skuEs.setWareId(skuInfo.getWareId());
        skuEs.setIsNewPerson(skuInfo.getIsNewPerson());
        skuEs.setImgUrl(skuInfo.getImgUrl());
        skuEs.setTitle(skuInfo.getSkuName());
        if (skuInfo.getSkuType().equals(SkuType.COMMON.getCode())) {
            //普通商品
            skuEs.setSkuType(0);
            skuEs.setPrice(skuInfo.getPrice().doubleValue());
            skuEs.setStock(skuInfo.getStock());
            skuEs.setSale(skuInfo.getSale());
            skuEs.setPerLimit(skuInfo.getPerLimit());
        }
        //3.调用方法添加ES
        skuRepository.save(skuEs);
    }

    //下架
    @Override
    public void lowerSku(Long skuId) {
        //下架 就是删除掉
        skuRepository.deleteById(skuId);
    }

    //获取爆款商品
    @Override
    public List<SkuEs> findHotSkuList() {
        //Spring Data是一个用于简化数据库根据方法名称自动实现查询功能
        //find read get 开头
        //管理条件 关键字
        //ES 中的分页 0表示第一页
        Pageable pageable = PageRequest.of(0, 10);
        Page<SkuEs> pageModel = skuRepository.findByOrderByHotScoreDesc(pageable);
        List<SkuEs> content = pageModel.getContent();
        return content;
    }

    //小程序
    //根据分类 查询商品
    @Override
    public Page<SkuEs> search(Pageable pageable, SkuEsQueryVo skuEsQueryVo) {
        //操作ES进行实现

        //1.向SkuEsQueryVo设置wareId仓库Id 当前登录用户的仓库Id
        skuEsQueryVo.setWareId(AuthContextHolder.getWareId());
        //这个线程的读写是在不同的模块中 如何正常获取的
        System.out.println("线程获取WareId: " + AuthContextHolder.getWareId());
        Page<SkuEs> pageModel = null;
        //2.调用SkuRepository方法 根据springData命名规则定义方法 进行条件查询
        //判断keyword 是否为空 如果为空 根据仓库Id + 分类id查询
        String keyword = skuEsQueryVo.getKeyword();
        //如果keyword不为空 根据id + 分类id + keyword进行查询
        if (StringUtils.isEmpty(keyword)) {
            pageModel = skuRepository.
                    //命名符合要求 基于SpringData操作ES
                    findByCategoryIdAndWareId(skuEsQueryVo.getCategoryId(), skuEsQueryVo.getWareId(), pageable);
        } else {
            //如果keyword不为空 根据仓库ID + keyword进行查询
            pageModel = skuRepository.
                    findByKeywordAndWareId(skuEsQueryVo.getKeyword(), skuEsQueryVo.getWareId(), pageable);
        }

        //查询商品目前参加的优惠活动
        //一个商品 只有一个活动 一个活动有多个规则 getContent得到集合
        List<SkuEs> skuEsList = pageModel.getContent();
        System.out.println("getContent: " + pageModel.getContent());
        if (!CollectionUtils.isEmpty(skuEsList)) {
            //遍历skuEsList 得到所有skuId
            List<Long> skuIdList =
                    skuEsList.stream()
                            .map(item -> item.getId())
                            .collect(Collectors.toList());

            //根据skuId列表 远程调用 调用service-activity里面的接口得到数据
            //返回一个Map<Long,List<String>>
            //key 是skuId值  value是List<String> 一个商品参加一个活动 一个活动里面可以有多个规则
            //一个活动可以有多个规则  就是活动里面的多个规则列表
            ///比如 有活动 中秋节满减活动
            ///中秋节 满减活动有两个规则 满20元 减去 2元  满28元 减去5元 List<String> 存的就是这两个规则
            Map<Long, List<String>> skuIdToRuleListMap =
                    activityFeignClient.findActivity(skuIdList);
            //远程调用
            //封装获取数据到skuES里面 ruleList属性里面
            if (skuIdToRuleListMap != null) {
                //封装获取数据到skuEs里面 ruleList属性里面
                skuEsList.forEach(skuEs -> {
                    skuEs.setRuleList(skuIdToRuleListMap.get(skuEs.getId()));
                });
            }
        }

        return pageModel;
    }

    //更新商品热度
    @Override
    public void incrHotScore(Long skuId) {
        //es叫索引库 做查询快 但是更新不快 es数据存到了磁盘当中 每次更新都是io操作
        //争对这个问题 使用Redis实现 + 1 约定redis这个值到达规则之后 才会去更新一个es
        //1.商品被用户查看一次 更新一次es里面hosScore

        //2.redis支持的数据类型 String List set hash ZSet(有序的Set,没有重复元素 每个成员关联一个score 根据评分进行排序)
        String key = "hotScore";
        //redis保存数据 每次加一
        Double hotScore = redisTemplate.opsForZSet().incrementScore(key, "skuId: " + skuId, 1);
        //es中的更新 规则
        if (hotScore % 10 == 0) {
            Optional<SkuEs> byId = skuRepository.findById(skuId);
            SkuEs skuEs = byId.get();
            skuEs.setHotScore(Math.round(hotScore));
            skuRepository.save(skuEs);
        }


    }
}
